package main

import (
	"bufio"
	"fmt"
	"io"
	"net"
	"os"
	"strconv"
	"strings"
)

// 下载文件
func download(conn net.Conn, filePath string, commandLine string) {
	// 打开文件
	file, err := os.OpenFile(filePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println("打开文件失败!", err)
	}
	defer file.Close()
	// 将get xxx发送给服务器
	conn.Write([]byte(commandLine))
	// 接收文件大小
	var sizeBytes = make([]byte, 1024)
	n, _ := conn.Read(sizeBytes)
	fileSize, _ := strconv.Atoi(string(sizeBytes[:n]))
	var curSize = 0
	var buf = make([]byte, 1024)
	for curSize < fileSize {
		// 依次读取
		n, _ := conn.Read(buf)
		file.Write(buf[:n])
		curSize += n
	}
	fmt.Println("文件下载成功!")
}

// 上传文件
func upload(conn net.Conn, filePath string) {
	fileInfo, err := os.Stat(filePath)
	if err != nil {
		fmt.Println("文件有误!", err)
	}
	var fileName = fileInfo.Name()
	var fileSize = fileInfo.Size()
	var input = "put " + fileName + " " + strconv.FormatInt(fileSize, 10)
	// 发送给服务器
	conn.Write([]byte(input))
	// 打开文件
	file, err := os.Open(filePath)
	if err != nil {
		fmt.Println("打开文件失败!", err)
	}
	defer file.Close()
	reader := bufio.NewReader(file)
	// 按照行发送
	for {
		lineBytes, err := reader.ReadBytes('\n')
		conn.Write(lineBytes)
		if err == io.EOF {
			// 读取结束
			break
		}
	}
	fmt.Println("文件上传成功!")
}

func main() {
	// 拨号服务器建立连接
	conn, err := net.Dial("tcp", "127.0.0.1:8080")
	if err != nil {
		fmt.Println("无法与服务器建立连接!", err)
	}
	// 接受服务器打招呼
	var msg = make([]byte, 1024)
	n, _ := conn.Read(msg)
	fmt.Println(string(msg[:n]))
	// put ./photo.png
	// filename size
	// content...
	fmt.Print("请输入执行命令:>>> ")
	reader := bufio.NewReader(os.Stdin)
	commandLine, _ := reader.ReadString('\n')
	// 去除前后空格
	commandLine = strings.TrimSpace(commandLine)
	// 按照空格切分
	var commandSlice = strings.Split(commandLine, " ")
	op, filePath := commandSlice[0], commandSlice[1]
	switch op {
	case "put":
		// 上传文件
		upload(conn, filePath)
	case "get":
		// 下载文件
		download(conn, filePath, commandLine)
	}
	defer conn.Close()
}
